<?php


namespace App\Repositories;


use App\Models\OrderProduct;
use App\Models\OrderShipment as Model;
use App\Traits\Logs;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use LTools\Repositories\RepositoryAbstract;

class OrderShipment extends RepositoryAbstract
{
    use Logs;

    /**
     * OrderShipment constructor.
     * @param Model $model
     * @author luffyzhao@vip.126.com
     */
    public function __construct(Model $model)
    {
        $this->model = $model;
    }

    /**
     * @param array $attributes
     * @param int|null $perPage
     * @param array $columns
     * @param string $pageName
     * @param int|null $page
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     * @author luffyzhao@vip.126.com
     */
    public function paginate(array $attributes, int $perPage = null, array $columns = ['*'], $pageName = 'page', int $page = null)
    {
        return $this->model->with(['order.products.product', 'customer'])->where(
            $attributes
        )->paginate($perPage, $columns, $pageName, $page);
    }

    /**
     * @param array $values
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
     * @throws \Throwable
     * @author luffyzhao@vip.126.com
     */
    public function autoStore(array $values)
    {
        $baseSystem = System::getGroup('base');

        $this->model->newQuery()
            ->where('type', '=', $values['type'])
            ->where('customer_id', '=', $values['customer_id'])
            ->where('status', '=', 0)
            ->orderByDesc('info')
            ->chunkById($baseSystem->get('wellen_count', 50), function (Collection $shipments) {
                /** @var Picking $picking */
                $picking = app(Picking::class);
                $picking->createPicking($shipments);
            });
    }


    /**
     * @param array $values
     * @author luffyzhao@vip.126.com
     */
    public function chooseStore(array $values)
    {
        $this->model->newQuery()
            ->whereIn('id', $values['ids'])
            ->where('status', '=', 0)
            ->orderByDesc('info')
            // 通过type分组
            ->get()->groupBy('type')->each(function ($shipments) {
                /** @var Picking $picking */
                $picking = app(Picking::class);
                $picking->createPicking($shipments);
            });
    }


    /**
     * @param array $values
     * @return Model
     * @throws \Exception
     */
    public function showPack(array $values)
    {
        try {
            /** @var Model $orderShipment */
            $orderShipment = $this->model->with(['pickingDetail.product.consumable', 'order'])->where($values)->firstOrFail();
            // config
            $orderShipment->setAttribute('config', $orderShipment->config()->whereIn('key', ['express_pdf', 'packing'])->get()->pluck('value', 'key'));

            if ($orderShipment->getAttribute('status') === 2) {
                return $orderShipment;
            }
        } catch (ModelNotFoundException $exception) {
            throw new \Exception("订单号不存在！");
        }
        throw new \Exception("出货单不是待打包状态");
    }

    /**
     * @param array $request
     * @param $id
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Relations\HasMany
     * @throws \Throwable
     * @author luffyzhao@vip.126.com
     */
    public function postPack(array $request, $id)
    {
        /** @var Model $orderShipment */
        $orderShipment = $this->model->newQuery()->where('id', '=', $id)->lockForUpdate()->firstOrFail();

        if ($orderShipment->getAttribute('status') === 2) {
            $orderShipment->setAttribute('status', 3);
            $orderShipment->saveOrFail();

            $this->recordLogs($orderShipment, "打包完成");

            $consumableJson = [];
            // 有使用耗材
            if ($request['consumable'] === 1) {
                // 扣耗材库存
                /** @var OrderProduct $products */
                foreach ($orderShipment->products as $products) {
                    /** @var \App\Models\Consumabl $consumable */
                    foreach ($products->consumable as $consumable) {
                        /** @var Consumable $repo */
                        $repo = app(Consumable::class);
                        $repo->decrementStocks($consumable->getAttribute('id'), $products->getAttribute('quantity'));
                        // 打包时用的耗材
                        $consumableJson[] = [
                            'name' => $consumable->getAttribute('name'),
                            'quantity' => $products->getAttribute('quantity')
                        ];
                    }
                }
            }

            // 扣包材库存
            /** @var Package $package */
            $package = app(Package::class);
            $package->decrementStocks($request['package_id'], 1);

            // 添加打包记录
            $orderShipment->order->pack()->create([
                'package_id' => $request['package_id'],
                'consumable_json' => $consumableJson,
            ]);


            try {
                $expressPdf = $orderShipment->config()->where('key', '=', 'express_pdf')->firstOrFail();
            } catch (ModelNotFoundException $exception) {
                throw new \Exception("没有快递面单，请联系管理员！！");
            }
            return $expressPdf;
        }
        throw new \Exception("出货单不是待打包状态");
    }
}
